<script>

  // 上一次向父级提交的高度
  var lastPostHeight = null

  // 每隔 100ms 向父级提交一次高度
  function postHeightChange() {
    var height = document.body.scrollHeight

    // console.log('postHeightChange: height: ', height );
    // console.log('postHeightChange: lastPostHeight: ', lastPostHeight);

    if (height !== lastPostHeight) {
      lastPostHeight = height
      postEvent('height-change', height, messageId)
    }
  }

  /**
   * 定义 VUE_OBJECT 的目的是为了要在 new Vue() 之前处理异步请求的问题
   *
   * jsonData 表单设计JSON
   * editData 表单数据JSON
   */
  var VUE_OBJECT = {
    el: '#app',
    store: store,
    mixins: [DeviceMixins, ExternalMixins],
    data: {
      // 操作动作模式（preview、edit、detail）
      action: "${action}",
      loading: false,
      jsonData: {},
      editData: {},
      desformCode: null,
      desformName: null,
      dialogVisible: false,
      dataId: null,
      // online数据id
      onlineDataId: null,
      remoteFuncs: {
        funcGetToken: function (resolve) {
          request({
            token: token,
            url: '${base}/desform/getQiniuUploadToken',
            method: 'GET',
            success: function (res) {
              if (res.success) {
                resolve(res.message)
              } else {
                console.error('图片token获取失败：', res)
              }
            }, fail: function (res) {
              console.error('图片token获取失败：' + res)
            }
          })
        },
      },
      // 是否是只读模式
      readOnly: false,
      // 当前登录的用户信息
      userInfo: null,
      // 是否在内部展示对话框
      innerDialog: innerDialog,
      // 自定义URL是否请求失败
      customURLFail: false,
      // 下一步路由配置
      nextRouteConfig: (${nextRouteConfig!"null"}),
      url: {
        base: '${base}',
        add: function (desformCode) {
          if (isExternal) {
            return '${base}/desform/ext/' + desformCode
          } else {
            return '${base}/desform/data/add'
          }
        },
        edit: function (desformCode, dataId) {
          if (isExternal) {
            return '${base}/desform/ext/' + desformCode + '/' + dataId
          } else {
            return '${base}/desform/data/edit'
          }
        },
        online: '${base}/online/cgform/api/crazyForm'
      }
    },
    created: function () {
      if (!this.innerDialog && document.body.style.backgroundColor === 'transparent') {
        document.body.style.backgroundColor = '#FFFFFF'
      }
    },
    mounted: function () {
      this.dialogVisible = true
      postHeightChange()
      setInterval(postHeightChange, 100)
    },
    methods: {
      handleClose: function () {
        postEvent('close', {}, messageId)
      },
      handleSubmit: function (event) {
        if (this.action === 'detail') {
          this.dialogVisible = false
          this.handleClose()
          return
        }
        var _this = this
        var getData = null
        if (this.innerDialog) {
          getData = event.getData
        } else {
          getData = this.$refs.generateForm.getData
        }
        getData().then(function (data) {
          // 数据校验成功，data 为获取的表单数据

          // 新数据和旧数据合并
          var assign = _this.editData
          for (var key in data) {
            if (data.hasOwnProperty(key)) {
              assign[key] = data[key]
            }
          }
          var params = {
            json: assign,
            formConfig: _this.jsonData.config,
            onlineForm: _this.jsonData.config.onlineForm,
            onlineDataId: _this.onlineDataId
          }


          // 判断是否在内部保存数据
          if (innerRequest) {
            _this.saveAllData(params)
          } else {
            postEvent('save', params, messageId)
          }
        }).catch(function (e) {
          // 数据校验失败
          console.error('数据校验失败: ', e)
        })
      },
      saveAllData: function (params) {
        var _this = this

        var url = _this.url.add(_this.desformCode), method = 'POST'
        var formData = {
          desformCode: _this.desformCode,
          desformDataJson: JSON.stringify(params.json)
        }
        if (_this.action !== 'add' && _this.dataId != null) {
          url = _this.url.edit(_this.desformCode, _this.dataId)
          method = 'PUT'
          formData['id'] = _this.dataId
        }

        _this.loading = true
        try {
          _this.saveStep1(url, params, method, formData)
        } catch (e) {
          _this.showMessage('error', '保存失败，请稍后重试')
          _this.loading = false
        }
      },

      // step.1 如果存在 onlineForm 就首先提交给online表单，获取到 id 后再提交到数据表
      saveStep1: function (url, params, method, formData) {
        var _this = this
        if (params.onlineForm) {
          formData['onlineFormCode'] = params.onlineForm
          if (_this.dataId != null) {
            params.json.id = params.onlineDataId
          }
          var onlineUrl = _this.url.online + '/' + params.onlineForm
          // online 特殊处理，防止因为java的toString破坏了格式
          var onlinePostJson = JSON.parse(JSON.stringify(params.json))
          for (var key in onlinePostJson) {
            if (onlinePostJson.hasOwnProperty(key)) {
              var item = onlinePostJson[key]
              if (typeof item === 'object') {
                onlinePostJson[key] = item == null ? null : JSON.stringify(item)
              }
            }
          }
          request({
            token: token,
            url: onlineUrl,
            method: method,
            data: onlinePostJson,
            success: function (res) {
              if (res.success) {
                // 成功提交到了onlineForm，获取到新增的uuid，且只有在新增时才提交
                formData['onlineFormDataId'] = res.result
                _this.saveStep2(url, formData, method)
              } else {
                _this.loading = false
                console.error('saveStep1.success=false: ', res)
                _this.showMessage('error', '保存失败，请稍后重试')
              }
            },
            fail: function (res) {
              _this.loading = false
              console.error('saveStep1.fail: ', res)
              _this.showMessage('error', '保存失败，请稍后重试')
            }
          })
        } else {
          _this.saveStep2(url, formData, method)
        }
      },
      // step.2 保存到desform数据库
      saveStep2: function (url, formData, method) {
        var _this = this
        //update-begin--Author:zhangdaihao  Date:20191003 for：实现表单的渲染，直接通过online dataid进行渲染，design_form_data无数据-------------------
        //如果是online的数据ID，则不走表单设计器的数据保存逻辑
        if (formData['id'] === 'ONLINE-DATA-TEMP-ID') {
          _this.loading = false
          this.showMessage('success', '保存成功！')
          //update-begin--Author:zhangdaihao  Date:20201102 for：online列表集成设计器表单，需要触发success事件------
          //online列表集成设计器表单，需要触发success事件
          postEvent('success', {}, messageId)
          //update-end--Author:zhangdaihao  Date:20201102 for：online列表集成设计器表单，需要触发success事件-----
          return
        }
        //update-end--Author:zhangdaihao  Date:20191003 for：实现表单的渲染，直接通过online dataid进行渲染，design_form_data无数据----------------------
        request({
          token: token,
          url: url,
          method: method,
          data: formData,
          success: function (res) {
            if (res.success) {
              _this.dataId = res.result
              formData.dataId = res.result
              _this.saveStep3(formData, method)
            } else {
              _this.loading = false
              console.error('saveStep2.success=false: ', res)
              _this.showMessage('error', '保存失败，请稍后重试')
            }
          },
          fail: function (res) {
            _this.loading = false
            console.error('saveStep2.fail: ', res)
            _this.showMessage('error', '保存失败，请稍后重试')
          }
        })
      },
      // step.3 提交到用户自定义url
      saveStep3: function (formData, method) {
        var _this = this
        var curl = _this.jsonData.config.customRequestURL
        if ((curl instanceof Array) && curl[0] && curl[0].url) {
          // console.log('提交到用户自定义url: ', curl[0], formData)
          _this.customURLFail = false
          // 判断是否带有 http(s)
          var url = curl[0].url.trim()
          if (!/^https?:\/{2}/.test(url)) {
            url = _this.url.base + url
          }
          request({
            token: token,
            url: url,
            method: method,
            data: formData,
            success: function (res) {
              _this.loading = false
              if (res.success) {
                _this.requestSuccess(formData.dataId)
              } else {
                console.error('saveStep2.success=false: ', res)
                _this.handleCustomURLFail(formData.dataId)
              }
            },
            fail: function (res) {
              _this.loading = false
              console.error('saveStep2.fail: ', res)
              _this.handleCustomURLFail(formData.dataId)
            }
          })
        } else {
          _this.requestSuccess(formData.dataId)
        }
      },
      handleCustomURLFail: function (dataId) {
        // 判断自定义URL是否启用事务
        if (this.jsonData.config.transactional === false) {
          this.customURLFail = true
          this.requestSuccess(dataId)
        } else {
          this.showMessage('error', '保存失败，自定义URL请求失败，请稍后重试')
          // 事务回滚（删除已保存的数据）
          this.rollbackTransactional(dataId)
        }
      },
      // 回滚事务
      rollbackTransactional: function (dataId) {
        var url = this.url.base + '/desform/data/delete'
        var params = '?id=' + dataId
        request({ token: token, url: url + params, method: 'DELETE' })
      },
      requestSuccess: function (dataId) {
        this.loading = false
        if (this.customURLFail) {
          this.customURLFail = false
          this.showMessage('warning', '保存成功，但自定义URL请求失败')
        } else if (!this.nextRouteConfig) {
          // 没有下一步路由配置的时候才显示保存成功
          this.showMessage('success', '保存成功！')
        }
        // 数据保存成功，如果当前是在外部链接模式，就将已保存的数据放到 LocalStorage 里
        if (isExternal) {
          this.setExternalSaved(dataId)
          // 外部链接无论如何都跳转到成功页面，而不走路由
          window.location.href = '${base}/desform/ext/success?desformCode=' + this.desformCode + '&dataId=' + dataId
        } else {
          // 内部链接需要根据路由配置来决定如何跳转，
          // 如果有路由配置就触发route-jump事件，
          // 没有就触发success事件，
          // 因为route-jump事件已经包含了success事件，无需重复触发。
          this.handleNextRoute(dataId)
        }
      },
      handleNextRoute: function (dataId) {
        var nextRouteConfig = this.nextRouteConfig
        if (nextRouteConfig) {
          // 1. 有路由配置，走路由跳转
          postEvent('route-jump', { nextRouteConfig: nextRouteConfig, dataId: dataId }, messageId)
        } else if (skip) {
          // 2. 没有路由配置，skip = true，跳转到成功页面
          window.location.href = '${base}/desform/success.html'
        } else {
          // 3. 没有路由配置，skip = false，触发success事件
          postEvent('success', {}, messageId)
        }
      },
      showMessage: function (type, message) {
        if (innerDialog) {
          postEvent('show-message', { type: type, message: message }, messageId)
        } else {
          this.$message[type](message)
        }
      },
      handleDialogChange: function (val) {
        postEvent('dialog-change', val, messageId)
      }
    }
  }

  /* 实例化VUE之前的前置操作 */

  var requestCount = 0

  // 查询出用户信息
  if (isExternal) {
    VUE_OBJECT.data.userInfo = {}
  } else {
    requestCount++
    request({
      token: token,
      url: '${base}/sys/user/getUserSectionInfoByToken',
      method: 'GET',
      success: function (res) {
        if (res.success) {
          VUE_OBJECT.data.userInfo = res.result
        } else {
          console.error('查询用户信息失败：', res)
        }
        requestCount--
      }, fail: function (res) {
        requestCount--
        console.error('查询用户信息失败：', res)
      }
    })
  }

  /* 将需要用到的数据通过 Freemarker表达式 取出来 */
  var dataSource = {}
  // 设计器构造JSON
  dataSource.jsonData = (${ designForm.desformDesignJson }) || {}
  // 设计器code
  dataSource.desformCode = '${ designForm.desformCode }'
  dataSource.desformName = '${ designForm.desformName }'

  // 判断是否为只读模式
  // ---- <#if isReadOnly ? exists>
  dataSource.readOnly = true
  // ---- </#if>

  // 判断是否有数据，若有数据则是修改，反之则是新增
  // ---- <#if designFormData ? exists>
  dataSource.dataId = '${ designFormData.id }'
  dataSource.onlineDataId = '${designFormData.onlineFormDataId!}'

  dataSource.editData = ${ designFormData.desformDataJson }

    /* 判断是否绑定了Online表单，如果绑定了就从online里取数据 */

    // 处理子表数据
    function handleSubTableData(key, cgformSubData) {
      var desformSubData = JSON.parse(decodeURIComponent(dataSource.editData[key]))
      //update-begin--Author:zhangdaihao  Date:20191003 for：实现表单的渲染，直接通过online dataid进行渲染，design_form_data无数据-------------------
      //如果表单设计data数据与物理表数据不一致，则以物理表数据为准
      if (desformSubData.length < cgformSubData.length) {
        desformSubData = cgformSubData
      }
      //update-end--Author:zhangdaihao  Date:20191003 for：实现表单的渲染，直接通过online dataid进行渲染，design_form_data无数据-------------------
      for (var i = 0; i < desformSubData.length; i++) {
        objectAssign(desformSubData[i], cgformSubData[i])
        desformSubData[i].id = undefined
      }
      dataSource.editData[key] = encodeURIComponent(JSON.stringify(desformSubData))
    }

  // 查询主表
  var codeFromJson = (dataSource.jsonData.config || {}).onlineForm
  var codeFromTable = '${ designForm.cgformCode! }'
  var tableName = (codeFromJson || codeFromTable)
  if (tableName) {
    // 从online表里查询数据，并和现有的合并
    requestCount++
    request({
      token: token,
      url: '${base}/online/cgform/api/form/table_name/' + tableName + '/' + dataSource.onlineDataId,
      method: 'GET',
      success: function (res) {
        if (res.success) {
          objectAssign(dataSource.editData, res.result)
          dataSource.editData.id = undefined

          // 判断是否存有子表
          for (var key in dataSource.editData) {
            if (dataSource.editData.hasOwnProperty(key)) {
              // var subTable = dataSource.editData[key];
              var split = key.split('sub-table-design_')
              if (split.length === 2 && split[0] === '') {
                var subTableName = split[1]
                // 查询子表（查询主表时已经返回了子表的数据，可以直接取出来处理）
                handleSubTableData(key, dataSource.editData[subTableName])
              }
            }
          }
        } else {
          console.error(res)
        }
        requestCount--
      }, fail: function (res) {
        requestCount--
        console.error(res)
      }
    })
  }
  // ---- </#if>
  // 上一个路由带过来的数据
  var routeData = (${routeData!'{}'})
  dataSource.editData = objectAssign(dataSource.editData||{}, routeData)

  // 根据用户设定的边距生成style
  var dialogOptions = dataSource.jsonData.config.dialogOptions
  if (dialogOptions) {
    var pd = dialogOptions.padding
    VUE_OBJECT.data['bodyStyle'] = {
      padding: pd.top + 'px ' + pd.right + 'px ' + pd.bottom + 'px ' + pd.left + 'px'
    }
  } else {
    VUE_OBJECT.data['bodyStyle'] = { padding: '25px 25px 30px 25px' }
  }

  /* 表单字段权限 */
  <#if authUserInfoJson ??>
  window['__authUserInfo'] =
  ${authUserInfoJson}
  </#if>

  <#if authInfoJson ??>
  var authInfo = (${authInfoJson} || []
  )
  var authsMap = {}
  for (var i = 0; i < authInfo.length; i++) {
    var auth = authInfo[i], temp = authsMap[auth.authComKey]
    if (temp instanceof Array) {
      temp.push(auth)
    } else {
      authsMap[auth.authComKey] = [auth]
    }
  }
  window['__authsMap'] = authsMap
  </#if>

  // console.log('dataSource: ', JSON.parse(JSON.stringify(dataSource)))

  // 检测所有的请求是否都已结束
  var timer = setInterval(function () {
    if (requestCount <= 0) {
      clearInterval(timer)
      //  合并数据
      objectAssign(VUE_OBJECT.data, dataSource)
      // ** 等待所有的前置请求都完成之后才进行实例化VUE操作
      new Vue(VUE_OBJECT)
    }
  }, 10)
</script>